Using Besu, the Java Ethereum Client with Linux/MacOS

Toolbelt: Besu included! Original photo by Jesse Orrico

Update: Pantheon is now Hyperledger Besu. For more information, see here.

This is the Linux/MacOS version of an article on installing Besu, the Java client for Ethereum:

  1. Linux
  2. Windows

Having some powerful tools in your toolbelt is essential for a Java developer, and one of the crucial tools for an Ethereum blockchain developer is the network client. This is the piece of software that communicates data to and from the blockchain. Among other things, the client: spins up nodes, acts as a peer discovery agent to see who else is participating in the network and validates and sends transactions.

This guide helps you install and setup this core part you need for programming on Ethereum with Java. Although there are some great networking clients out there, Besu is the only one written in Java.

Besu is an open-source, Apache 2.0 licensed Ethereum client written in Java. It is mainnet compatible, has a modular architecture, and has privacy and permissioning features as well as new consensus algorithms.

This is the first of a series of step-by-step guides to install and configure the Besu client on Linux/macOS/Windows. This guide focuses on Linux operating system, but you can use many of the commands and steps on macOS with some basic modifications.

Try Besu with Docker

Before installing, I would suggest anyone wanting to setup and install Besu for the first time to try it out using our Docker images. The requirements to do so are having Docker installed and using Linux or macOS. You can use a single docker command to run a mainnet, local or rinkeby version of Besu, and then use curl or similar tools to get or post data to the running node.

For quick, temporary tests this guide uses /tmp/besu/dev/, /tmp/besu/mainnet/, /tmp/besu/rinkeby/ as mount volumes, which are automatically cleaned at every boot. You can create other folders instead, but whichever option you choose, make sure you create the folders first.

$ mkdir -p /tmp/besu/dev/
$ mkdir -p /tmp/besu/mainnet/
$ mkdir -p /tmp/besu/rinkeby/

Here are some examples:

Mainnet Node:

docker run hyperledger/besu:latest

Local test Node with Websockets and HTTP RPC services enabled:

docker run -p 8545:8545 -p 8546:8546 --mount type=bind,source=/tmp/besu/dev,target=/var/lib/besu hyperledger/besu:latest --miner-enabled --miner-coinbase fe3b557e8fb62b89f4916b721be55ceb828dbd73 --rpc-http-cors-origins="all" --rpc-ws-enabled --network=dev

Rinkeby Node:

docker run -p 30303:30303 --mount type=bind,source=/tmp/besu/rinkeby,target=/var/lib/besu hyperledger/besu:latest --network=rinkeby

While the node is running, you can use another terminal window to interact with the node.

For example, using curl to call the eth_chainId RPC method:

curl -X POST --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' localhost:8545

Getting started with Linux

Two installation methods are available:

Requirements: For both of these methods, Besu needs the Java JDK installed on your machine. Current versions of Besu require Java JDK 11+ installed.

Binary install

Remember to have at least 4GB of RAM if running a private network, and review the further requirements for other installation types.

  1. Download the Besu binaries.

You can use wget to do this.

$ sudo apt install wget
$ cd ~/bin/
$ wget   https://bintray.com/hyperledger-org/besu-repo/download_file?file_path=besu-1.3.5-SNAPSHOT.tar.gz -O besu.tar.gz
$ wget https://bintray.com/hyperledger-org/besu-repo/download_file?file_path=besu-1.3.5-SNAPSHOT.tar.gz -O besu.tar.gz

$HOME/bin/ and $HOME/.local/{bin,opt,usr} are the recommended install folders for local user binaries on machines used by a single user. Other options are available such as /opt/local/ or /usr/local/bin/ depending on your local setup and preference. Read this Stack Exchange thread for more details.

  1. Unpack the compressed file:
$ tar -xzf besu.tar.gz
$ cd besu-<version>

Replace with whichever release you downloaded.

  1. Confirm the download isn't corrupted and check the version .The output should return the Besu and JDK version.
$ bin/besu --version
besu/v1.3.5-dev-bb0ba9b7/linux-x86_64/oracle_openjdk-java-11

Build from Source

Two options are available: installing and running locally or on a VM.

This guide focuses on the local solution.

  1. Clone the Besu codebase
$ cd ~/bin/
$ git clone --recursive https://github.com/hyperledger/besu
  1. Build Besu
$ cd besu/
$ ./gradlew build -x test
  1. Choose distribution version and check version.
$ cd build/distributions/
$ tar -xzf besu-<version>.tar.gz
$ cd besu-<version>/
$ bin/besu --version
$ bin/besu --help

Replace with whichever release you downloaded.

Config

No additional configuration is necessary for Besu to run correctly. Each different network type (including mainnet) set by the --network command line flags automatically loads the appropriate default configuration.

If you need to change the settings, these options are either configured at Node or Network-level. Network-level settings are defined in the genesis file and are loaded by every Node connected to that specific network. Whereas Node-level settings are modified either in the node configuration file, or through command line flags.

For more information on configuration, read the corresponding documentation.

Starting Besu

After you have completed the above steps, you can continue using this distribution with the regular Starting Besu guide.

For a quick preview, this could be an HTTP request on a dev network Node running with docker.

$ docker run -p 8545:8545 --mount type=bind,source=/tmp/besu/dev,target=/var/lib/besu hyperledger/besu:latest --miner-enabled --miner-coinbase fe3b557e8fb62b89f4916b721be55ceb828dbd73 --rpc-http-cors-origins="all" --rpc-http-enabled --network=dev

This is how you build a request calling the eth_chainId method.

String payload='{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}';
String requestUrl="http://localhost:8545";
sendRequest(requestUrl, payload);

And the method implementation:

public static String sendRequest(String requestUrl, String payload) {
    try {
        URL url = new URL(requestUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Accept", "application/json");
        connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        OutputStreamWriter outputWriter = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");

        outputWriter.write(payload);
        outputWriter.close();

        BufferedReader buffer = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        StringBuffer jsonString = new StringBuffer();
        String line;
        while ((line = buffer.readLine()) != null) {
                jsonString.append(line);
        }
        buffer.close();

        connection.disconnect();
        return jsonString.toString();
    } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
    }
}

That request should return the following result:

{
  "jsonrpc" : "2.0",
  "id" : 1,
  "result" : {
    "startingBlock" : "0x0",
    "currentBlock" : "0x2d0",
    "highestBlock" : "0x66c0"
  }
}

Find more information in the Besu documentation.